package com.md.livingwidget.toast;

import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.md.basedpc.PHUtils;
import com.md.basedpc.common.PHThreadPool;
import com.md.livingwidget.R;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Stack;

import androidx.annotation.DrawableRes;
import androidx.core.app.NotificationManagerCompat;

/**
 * create by 朱大可on 2020年03月10日17:03:58
 * Toast 基础UI
 */
public class PHToast {
    private static Object iNotificationManagerObj;
    private static Field sField_TN;
    private static Field sField_TN_Handler;
    private static PHLoading dialog;

    public static Stack<View> toastStack = new Stack();

    static {
        try {
            sField_TN = Toast.class.getDeclaredField("mTN");
            sField_TN.setAccessible(true);
            sField_TN_Handler = sField_TN.getType().getDeclaredField("mHandler");
            sField_TN_Handler.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void hook(Toast toast) {
        try {
            Object tn = sField_TN.get(toast);
            if (sField_TN_Handler != null) {
                Handler preHandler = (Handler) sField_TN_Handler.get(tn);
                sField_TN_Handler.set(tn, new SafelyHandlerWrapper(preHandler));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void shotBigToast(Context context, String text) {
        shotBigToast(context, R.drawable.ph_toast_big_bg, R.drawable.ph_toast_tip_success, text);
    }

    public static void shotBigToast(Context context, @DrawableRes int tipResource, String text) {
        shotBigToast(context, R.drawable.ph_toast_big_bg, tipResource, text);
    }

    public static void shotBigToast(Context context, @DrawableRes int bgResource, @DrawableRes int tipResource, String text) {
        if (PHUtils.isEmpty(text)) return;

        PHThreadPool.getInstance().executeUIThread(() -> {
            Toast toast = new Toast(context);
            toast.setGravity(Gravity.CENTER, 0, 0);
            LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.ph_toast_big, null);
            ImageView imageView1 = view.findViewById(R.id.ph_toast_image);
            ImageView imageView2 = view.findViewById(R.id.ph_toast_tip);
            TextView textView1 = view.findViewById(R.id.ph_toast_text);
            imageView1.setImageResource(bgResource);
            imageView2.setImageResource(tipResource);
            textView1.setText(text);
            if (TextUtils.isEmpty(text))
                textView1.setVisibility(View.GONE);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_SHORT);

            hook(toast);
            if (isNotificationEnabled(context)) {
                toast.show();
            } else {
                showSystemToast(toast);
            }
        });
    }

    public static void showSingleToast(Context context, String text) {
        PHThreadPool.getInstance().executeUIThread(() -> {
            if (PHUtils.isEmpty(text)) return;
            Toast toast = new Toast(context);
            toast.setGravity(Gravity.CENTER, 0, 0);
            LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.ph_toast, null);
            TextView textView1 = view.findViewById(R.id.ph_toast_text);
            textView1.setText(text);
            if (TextUtils.isEmpty(text))
                textView1.setVisibility(View.GONE);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_SHORT);

            hook(toast);
            if (isNotificationEnabled(context)) {
                toast.show();
            } else {
                ToastUtil.getInstance(context).makeText(view, 0x01).show();
//                showSystemToast(toast);
            }
        });
    }

    /**
     * 弹出指定位置
     *
     * @param context
     * @param text    内容
     * @param gravity 位置
     * @param xOffset x偏移量
     * @param yOffset y偏移量
     */
    public static void showLeftSingleToast(Context context, String text, int gravity, int xOffset, int yOffset) {
        PHThreadPool.getInstance().executeUIThread(() -> {
            if (PHUtils.isEmpty(text)) return;
            Toast toast = new Toast(context);
            toast.setGravity(gravity, xOffset, yOffset);
            LayoutInflater inflater = LayoutInflater.from(context);
            View view = inflater.inflate(R.layout.ph_toast, null);
            TextView textView1 = view.findViewById(R.id.ph_toast_text);
            textView1.setText(text);
            if (TextUtils.isEmpty(text))
                textView1.setVisibility(View.GONE);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_LONG);

            hook(toast);
            if (isNotificationEnabled(context)) {
                toast.show();
            } else {
                ToastUtil.getInstance(context).makeText(view, 0x01).show();
            }
        });
    }

    /**
     * 显示系统Toast
     * modify by liyue, targetSdkVersion=30编译通不过
     */
    private static void showSystemToast(Toast toast) {
//        try {
//            Method getServiceMethod = Toast.class.getDeclaredMethod("getService");
//            getServiceMethod.setAccessible(true);
//            if (iNotificationManagerObj == null) {
//                iNotificationManagerObj = getServiceMethod.invoke(null);
//
//                Class iNotificationManagerCls = Class.forName("android.app.INotificationManager");
//                Object iNotificationManagerProxy = Proxy.newProxyInstance(toast.getClass().getClassLoader(), new Class[]{iNotificationManagerCls}, new InvocationHandler() {
//                    @Override
//                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                        //强制使用系统Toast
//                        if ("enqueueToast".equals(method.getName())
//                                || "enqueueToastEx".equals(method.getName())) {  //华为p20 pro上为enqueueToastEx
//                            args[0] = "android";
//                        }
//                        return method.invoke(iNotificationManagerObj, args);
//                    }
//                });
//                Field sServiceFiled = Toast.class.getDeclaredField("sService");
//                sServiceFiled.setAccessible(true);
//                sServiceFiled.set(null, iNotificationManagerProxy);
//            }
            toast.show();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 消息通知是否开启
     *
     * @return
     */
    private static boolean isNotificationEnabled(Context context) {
        NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
        boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
        return areNotificationsEnabled;
    }

    /**
     * 显示loading动画
     *
     * @param context
     */
    public static void showLoading(Context context) {
        showLoading(context, null, 1, null);
    }

    /**
     * 显示loading动画
     *
     * @param context
     * @param msg     需要在loading下面显示的文字
     */
    public static void showLoading(Context context, String msg) {
        showLoading(context, msg, 1, null);
    }

    /**
     * 显示loading动画
     *
     * @param context
     * @param onCancelListener loading消失的回调
     */
    public static void showLoading(Context context, DialogInterface.OnCancelListener onCancelListener) {
        showLoading(context, null, 1, onCancelListener);
    }

    /**
     * 显示loading动画
     *
     * @param context
     * @param msg              需要在loading下面显示的文字
     * @param onCancelListener loading消失的回调
     */
    public static void showLoading(Context context, String msg, DialogInterface.OnCancelListener onCancelListener) {
        showLoading(context, msg, 1, onCancelListener);
    }

    /**
     * 显示loading动画
     *
     * @param context
     * @param msg              需要在loading下面显示的文字
     * @param cancelType       0 不可取消 1 返回键可取消 2 点哪都能取消
     * @param onCancelListener loading消失的回调
     */
    public static void showLoading(Context context, String msg, int cancelType, DialogInterface.OnCancelListener onCancelListener) {
        PHThreadPool.getInstance().executeUIThread(() -> {
            if (dialog != null && dialog.isShowing())
                dialog.dismiss();
            dialog = new PHLoading(context, msg, cancelType);
            dialog.setOnCancelListener(onCancelListener);
            dialog.show();
        });
    }

    /**
     * 显示loading动画
     *
     * @param msg 需要在loading下面显示的文字
     */
    public static void changeLoadingText(String msg) {
        PHThreadPool.getInstance().executeUIThread(() -> {
            if (dialog != null && dialog.isShowing())
                dialog.setText(msg);
        });
    }

    public static void cancelLoading() {
        PHThreadPool.getInstance().executeUIThread(() -> {
            if (dialog != null && dialog.isShowing()) {
                dialog.dismiss();
            }
        });
    }
}
